﻿#ifndef __UTILS_H__
#define __UTILS_H__

#include "types.h"
#include <QDateTime>
#include <QDataStream>

#define BIT(x)			((1U << (x)))
#define BITS(s, e)		((0xffffffff << (s)) & (0xffffffff >> (31 - (e))))

class Utils {
public:
    static u8 get_xor_checksum(u8 *bytes, int offset, int length) {
        u8 check = 0;
        for (int i = offset; i < length+offset; i++) {
            check = (u8)(check ^ bytes[i]);
        }
        return check;
    }
    static uint8_t calc_checksum(uint8_t *tmpbuf, uint8_t len)
    {
        uint8_t i;
        uint8_t chksum;

        chksum = 0;
        if (len != 0) {
            for (i = 0; i < len; ++i) {
                chksum += tmpbuf[i];
            }
            chksum = 0xFF - chksum;
        }
        return chksum;
    }

    static u8 decode_u8(u8 *buff) {
        return buff[0];
    }

    static u16 decode_u16(u8 *buff) {
        return (((u16)(buff[1]) << 8) | buff[0]);
    }
    static u32 decode_u24(u8 *buff) {
        return ((u32)decode_u8(buff+2))<<16 | decode_u16(buff);
    }
    static u32 decode_u32(u8 *buff) {
        return ((u32)(decode_u16(buff + 2)) << 16 | decode_u16(buff));
    }

    static float decode_float(u8 *buff) {
        float value;
        u8 *p_f = (u8 *)&value;
        p_f[0] = buff[0];
        p_f[1] = buff[1];
        p_f[2] = buff[2];
        p_f[3] = buff[3];
        return value;
    }

    static s8 decode_s8(u8 *buff) {
        return (s8)buff[0];
    }

    static s16 decode_s16(u8 *buff) {
        return (s16)decode_u16(buff);//(((s16)(buff[1]) << 8) | buff[0]);
    }

    static s32 decode_s32(u8 *buff) {
        return (s32)decode_u32(buff);  //((s32)(decode_s16(buff + 2)) << 16 | decode_s16(buff));
    }

    static void encode_u8(u8 *buff, u8 data) {
        buff[0] = data;
    }

    static void encode_u16(u8 *buff, u16 data) {
        encode_u8(buff++, (u8)data);
        encode_u8(buff, (u8)(data>>8));
    }

    static void encode_u24(u8 *buff, u32 data) {
        encode_u16(buff, (u16)data);
        buff += 2;
        encode_u8(buff, (u8)(data>>16));
    }

    static void encode_u32(u8 *buff, u32 data) {
        encode_u16(buff, (u16)data);
        encode_u16(buff + 2, (u16)(data >> 16));
    }

    static void encode_float(u8 *buff, float data) {
        float *p_f = &data;
        u32 *p_u32 = (u32 *)p_f;
        u32 v = *p_u32;
        encode_u32(buff, v);
    }

    static void encode_s8(u8 *buff, s8 data) {
        buff[0] = data;
    }

    static void encode_s16(u8 *buff, s16 data) {
        encode_s8(buff++, (u8)data);
        encode_s8(buff, (u8)(data>>8));
    }

    static void encode_s32(u8 *buff, s32 data) {
        encode_s16(buff, (u16)data);
        encode_s16(buff + 2, (u16)(data >> 16));
    }
    static qint64 timestamp_msec(){
        return QDateTime::currentMSecsSinceEpoch();
    }

    static QString ByteArrayToHexString(QByteArray &ba)
    {
        QString ret;
        for (int i = 0; i < ba.count(); ++i)
        {
             ret.append( QString("0x%1,").arg((quint8)ba.at(i),2,16,QLatin1Char('0')).toLower());
        }
        return ret;
    }

    static u32 get_config_crc32(u8 *buff, int length) {
        const u8 *buff_end;
        u32 crc = 0xFFFFFFFF;
        for (buff_end = buff + length; buff < buff_end; buff++) {
            u8 value = *buff;
            u8 i;

            for (i = 0; i < 8; i++) {
                if (((crc ^ value) & 1) != 0) {
                    crc = (crc >> 1) ^ 0xEDB88320U;
                } else {
                    crc >>= 1;
                }

                value >>= 1;
            }
        }

        return crc ^ 0xFFFFFFFFU;
    }

    static s16 rpm_to_speed(s16 rpm) {
        float GBn = 6.15f;// %传动比
        float Wheel_r = 0.275f;// %驱动轮半径，单位m
        float Wheel_l = 2 * 3.1416f * Wheel_r;

        float speed = (float)rpm*60.0f/GBn * Wheel_l / 1000.0f;
        s16 speed_s = (s16)speed;
        if (speed - speed_s >= 0.5f) {
            speed_s += 1;
        }else if (speed - speed_s <= -0.5f) {
            speed_s += -1;
        }
        return speed_s;
    }
    static s16 speed_to_rpm(s16 speed) {
        float GBn = 6.15f;// %传动比
        float Wheel_r = 0.275f;// %驱动轮半径，单位m
        float Wheel_l = 2 * 3.1416f * Wheel_r;
        float rpm = (float)speed*1000/Wheel_l*GBn/60.0f;

        s16 rpm_s = (s16)rpm;
        if (rpm - rpm_s >= 0.5f) {
            rpm_s += 1;
        }else if (rpm - rpm_s <= -0.5f) {
            rpm_s += -1;
        }
        return rpm_s;
    }

    static s16 value_aline_up(s16 value, s16 align) {
        s16 mod = value % align;
        if (mod == 0) {
            return value;
        }
        return (value + (align - mod));
    }
    static s16 value_aline_down(s16 value, s16 align) {
        s16 mod = value % align;
        if (mod == 0) {
            return value;
        }
        return (value - mod);
    }
    static u32 get_crc32(const u8 *data, int len);
    static int get_file_info(QString file_name, u32 &crc32);
    static QByteArray &Random(int len);
    static QByteArray HmacSha256(QByteArray &key, QByteArray &message);
    static bool dirExist(QString path,  bool create = false);
    static u16 crc16_update_byte(u16 crc, u8 value);
    static u16 crc16_update(u16 crc, const u8 *data, u16 size);
    static u16 crc16_get(const u8 *data, u16 size);
};


#endif /* __UTILS_H__ */
